import 'dart:async';
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'ble_action_type.dart';
import 'ble_device.dart';

///Ble插件
class BlePlugin {

  /// Ble插件标识
  static const String  CHANNEL_SINGLE= "bluetooth_plugin_channel";

  static const MethodChannel _channel =  const MethodChannel(CHANNEL_SINGLE);

  /// 监听器对象
  static BlePluginListener listener;

  /// 添加消息监听
  static void addListener(ListenerValue func) {
    if (listener == null) {
      listener = BlePluginListener(_channel);
    }
    listener.addListener(func);
  }

  /// 移除消息监听
  static void removeListener(ListenerValue func) {
    if (listener == null) {
      listener = BlePluginListener(_channel);
    }
    listener.removeListener(func);
  }

  ///初始化ble
  static Future<void> init() async{
    return await _channel.invokeMethod('init');
  }

  ///全局配置
  static Future<void> globalConfig({enableLog, retryCount, interval, splitWriteNum, connectOverTime, operateTimeout}) async{
    return await _channel.invokeMethod('globalConfig', {
      "retryCount": retryCount,
      "enableLog": enableLog,
      "interval": interval,
      "splitWriteNum": splitWriteNum,
      "connectOverTime": connectOverTime,
      "operateTimeout": operateTimeout
    });
  }

  ///设置扫描规则
  static Future<void> initScanRule({serviceUuids, names,mac,bool isAutoConnect=false,int scanTimeOut=15000}) async{
    return await _channel.invokeMethod('initScanRule',{
      "serviceUuids": serviceUuids,
      "names": names,
      "mac": mac,
      "isAutoConnect": isAutoConnect,
      "scanTimeOut": scanTimeOut
});
  }

  ///扫描设备
  static Future<void> scan() async{
    return await _channel.invokeMethod('scan');
  }

  ///通过扫描到的BleDevice对象进行连接。
  static Future<void> connectByDevice({
    @required BleDevice device, // 外设设备
  }) async {
    return await _channel.invokeMethod('connectByDevice', {
      "device": device,
    });
  }

  /// 通过mac地址对应的对象进行连接
  static Future<void> connectByMac({
    @required BleDevice bleDevice, // 外设对象
  }) async {
    return await _channel.invokeMethod('connectByMac', {
      "bleDevice": bleDevice.toJson(),
    });
  }

  /// 扫描并连接
  static Future<void> scanAndConnect() async {
    return await _channel.invokeMethod('scanAndConnect');
  }

  /// 中止扫描
  static Future<void> cancelScan() async {
    return await _channel.invokeMethod('cancelScan');
  }

  /// 订阅通知
  static Future<void> notify({
    @required
        BleDevice bleDevice,
    @required
        String  uuid_service,
    @required
    String uuid_characteristic_notify
  }) async {
    return await _channel.invokeMethod('notify', {
      "bleDevice": bleDevice.toJson(),
      "uuid_service": uuid_service,
      "uuid_characteristic_notify":uuid_characteristic_notify
    });
  }

  ///取消订阅
  static Future<void> stopNotify({
    @required BleDevice bleDevice,
    @required String uuid_service,
    @required String uuid_characteristic_notify
  }) async {
    return await _channel.invokeMethod('stopNotify', {
      "bleDevice": bleDevice.toJson(),
      "uuid_service": uuid_service,
      "uuid_characteristic_notify":uuid_characteristic_notify
    });
  }

  ///订阅通知indicate
  static Future<void> indicate({
    @required       bleDevice,
    @required       uuid_service,
    @required       uuid_characteristic_indicate
  }) async {
    return await _channel.invokeMethod('indicate', {
      "bleDevice": bleDevice,
      "uuid_service": uuid_service,
      "uuid_characteristic_indicate": uuid_characteristic_indicate
    });
  }

  /// 取消订阅通知indicate，并移除数据接收的回调监听
  static Future<void> stopIndicate({
    @required  BleDevice     bleDevice,
    @required   String    uuid_service,
    @required   String    uuid_characteristic_indicate
  }) async {
    return await _channel.invokeMethod('stopIndicate', {
      "bleDevice": bleDevice,
      "uuid_service": uuid_service,
      "uuid_characteristic_indicate": uuid_characteristic_indicate
    });
  }

  ///写操作
  static Future<void> write({
    @required  BleDevice     bleDevice,
    @required   String    uuid_service,
    @required String uuid_characteristic_write,
  }) async {
    return await _channel.invokeMethod('write', {
      "bleDevice": bleDevice,
      "uuid_service": uuid_service,
      "uuid_characteristic_write": uuid_characteristic_write
    });
  }

  /// 读操作
  static Future<void> read({
    @required  BleDevice     bleDevice,
    @required   String      uuid_service,
    @required    String       uuid_characteristic_read
}) async {
    return await _channel.invokeMethod('read',{
      "bleDevice": bleDevice,
      "uuid_service": uuid_service,
      "uuid_characteristic_read": uuid_characteristic_read
    });
  }

  /// 获取设备强度
  static Future<void> readRssi({@required BleDevice bleDevice}) async {
    return await _channel.invokeMethod('readRssi',{
      "bleDevice":bleDevice
    });
  }

  /// 设置MTU。
  static Future<void> setMtu({@required BleDevice bleDevice,@required int mtu}) async {
    return _channel.invokeMethod('setMtu',{
      "bleDevice":bleDevice,
      "mtu":mtu
    });
  }

  /// 设置连接的优先级
  static Future<void> requestConnectionPriority({
    @required BleDevice bleDevice,
    @required int connectionPriority // 设置连接的优先级
  }) async {
    return _channel.invokeMethod('requestConnectionPriority', {
      "bleDevice":bleDevice,
      "connectionPriority": connectionPriority,
    });
  }

  /// 断开某个设备
  static Future<void> disconnect({
    @required BleDevice bleDevice, //设备
  }) async {
    return _channel.invokeMethod('disconnect', {
      "bleDevice": bleDevice,
    });
  }

  /// 断开所有设备
  static Future<void> disconnectAllDevice() async {
    return _channel.invokeMethod('disconnectAllDevice');
  }

  ///退出使用，清理资源
  static Future<void> destroy() async {
    return _channel.invokeMethod('destroy');
  }

  ///获取所有已连接设备
  static Future<void> getAllConnectedDevice() async {
    return _channel.invokeMethod('getAllConnectedDevice');
  }

  ///获取某个已连接设备的BluetoothGatt
  static Future<void> getBluetoothGatt({
  @required BleDevice bleDevice, //设备
  }) async {
    return _channel.invokeMethod('getBluetoothGatt', {
      "bleDevice": bleDevice,
    });
  }

  /// 获取某个已连接设备的所有Service
  static Future<void> getBluetoothGattServices({
    @required BleDevice bleDevice, //设备
  }) async {
    return _channel.invokeMethod('getBluetoothGattServices', {
      "bleDevice": bleDevice
    });
  }



  /// 判断某个设备是否已连接
  static Future<void> isConnected({
    @required BleDevice bleDevice, //设备
  }) async {
    return _channel.invokeMethod('isConnected', {
      "bleDevice": bleDevice
    });
  }

  /// 判断某个设备的当前连接状态
  static Future<void> getConnectState({
    @required BleDevice bleDevice, //设备
  }) async {
    return _channel.invokeMethod('getConnectState', {
      "bleDevice": bleDevice
    });
  }

  //*******************************博声接口开始***********************************//

  /// 初始化博声sdk
  static Future<void> initBleHeartSdk() async {
    return _channel.invokeMethod('initBleHeartSdk', null);
  }

  /// 初始化博声扫描规则
  static Future<void> initBleHeartScanRule({
    @required String deviceName, //设备名称,多个用分号隔开
    int scanTimeOut//扫描时间
  }) async {
    return _channel.invokeMethod('initBleHeartScanRule', {
      "deviceName":deviceName,
      "scanTimeOut":scanTimeOut
    });
  }

  /// 开始扫描
  static Future<void> startHeartScan(
  {String mac}
      ) async {
    return _channel.invokeMethod('startHeartScan', {
      "mac":mac
    });
  }

  /// 开始连接
  static Future<void> startHeartConnect(
      @required String deviceName
      ) async {
    return _channel.invokeMethod('startHeartConnect', {
      "deviceName":deviceName
    });
  }

//*******************************博声接口结束***********************************//
}

/**
 *Ble监听器对象 
  */
class BlePluginListener {
  /// 监听器列表
  static Set<ListenerValue> listeners = Set();

  BlePluginListener(MethodChannel channel) {
    // 绑定监听器
    channel.setMethodCallHandler((methodCall) async {
      // 解析参数
      Map<String, dynamic> arguments = jsonDecode(methodCall.arguments);

      switch (methodCall.method) {
        case 'onListener':
          // 获得原始类型和参数
          String typeStr = arguments['type'];
          var params = arguments['params'];

          // 封装回调类型和参数
          BleActionType type;

          // 初始化类型
          for (var item in BleActionType.values) {
            if (item.toString().replaceFirst("BleActionType.", "") ==
                typeStr) {
              type = item;
              break;
            }
          }

          // 没有找到类型就返回
          if (type == null) {
            throw MissingPluginException();
          }
          // 回调触发
          for (var item in listeners) {
            item(type, params);
          }

          break;
        default:
          throw MissingPluginException();
      }
    });
  }

  /// 添加消息监听
  void addListener(ListenerValue func) {
    listeners.add(func);
  }

  /// 移除消息监听
  void removeListener(ListenerValue func) {
    listeners.remove(func);
  }
}

/// 监听器值模型
typedef ListenerValue<P> = void Function(BleActionType type, P params);
